package com.course.gateway.service;

import com.course.common.response.BaseResponse;
import com.course.gateway.entity.GatewayEntity;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.net.URI;
import java.util.*;

/**
 * @PROJECT_NAME: course
 * @DESCRIPTION: 实现动态服务网关
 * @Author: 涂玄武
 * @DATE: 2021/7/27 15:40
 */
@Service
public class GatewayService implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    @Resource
    private RouteDefinitionWriter routeDefinitionWriter;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    //从数据库中加载所有网关配置
    public BaseResponse loadAllLoadRoute() {
        //从数据库中查询所有网关配置,此处先初始化为空List
        List<GatewayEntity> gatewayEntities = new ArrayList<>();
        for (GatewayEntity entity : gatewayEntities) {
            loadRoute(entity);
        }
        return new BaseResponse().success("网关配置加载成功!");
    }

    /**
     * 加载网关配置
     * @param gatewayEntity
     */
    public void loadRoute(GatewayEntity gatewayEntity) {
        RouteDefinition definition = new RouteDefinition();
        Map<String, String> predicateParams = new HashMap<>(8);
        Map<String, String> filterParams = new HashMap<>(8);
        //断言，作为路由的匹配条件，对应 RouteDefinition 数组
        PredicateDefinition predicateDefinition = new PredicateDefinition();
        //请求路径过滤-截取
        FilterDefinition filterDefinition = new FilterDefinition();
        URI uri = null;
        if ("0".equals(gatewayEntity.getRouteType())) {
            //若配置路由type为0，则从注册中心获取服务地址
            uri = UriComponentsBuilder.fromUriString("lb://" + gatewayEntity.getRouteUrl() + "/").build().toUri();
        } else {
            uri = UriComponentsBuilder.fromHttpUrl(gatewayEntity.getRouteUrl()).build().toUri();
        }
        //定义路由唯一ID
        definition.setId(gatewayEntity.getRouteId());
        //断言配置
        predicateDefinition.setName("Path");
        //路由转发地址
        predicateParams.put("pattern", gatewayEntity.getRoutePattern());
        predicateDefinition.setArgs(predicateParams);

        //路径去前缀
        filterDefinition.setName("StriPrefix");
        filterParams.put("_genkey_0", "1");
        filterDefinition.setArgs(filterParams);
        definition.setPredicates(Arrays.asList(predicateDefinition));
        definition.setFilters(Arrays.asList(filterDefinition));
        definition.setUri(uri);
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }


}
